package com.chinatechstar.component.commons.utils;


import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.StringUtils;

import java.sql.Time;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yanghaolin
 * @date 2022/6/2
 * @apiNote
 */
public class DateUtil {
    private static final ThreadLocal<Map<String, SimpleDateFormat>> threadLocal = new ThreadLocal<>();
    private static final Calendar calendar = Calendar.getInstance();

    public static final String YY_MM_DD = "yyMMdd";

    public static final String YY_MM = "yyMM";

    public static final String YY = "yy";

    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYYMMDD = "yyyy年MM月dd日";

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String getCodeByNowTime(){
        return dataToStr(new Date(),YYYYMMDDHHMMSS);
    }

    private static SimpleDateFormat getFormater(String pattern) {
        Map<String, SimpleDateFormat> formaterMap = threadLocal.get();
        if (formaterMap == null) {
            formaterMap = new HashMap<String, SimpleDateFormat>();
            threadLocal.set(formaterMap);
        }
        if (!formaterMap.containsKey(pattern)) {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            formaterMap.put(pattern, sdf);
        }
        return formaterMap.get(pattern);
    }

    /**
     * @param dateStr     时间字符串
     * @param formateType 格式化的类型 形如 yyyy-MM-dd HH:mm:ss yyyy-MM-dd 等
     * @return Date
     * @throws RuntimeException 抛出异常
     */
    public static Date stringToDate(String dateStr, String formateType) {
        SimpleDateFormat sdf = getFormater(formateType);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期转换失败");
        }
    }
    public static boolean isBefore90Days(Date date) {
        Date now = new Date();
        long millisecondsPerDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
        long currentTimestamp = now.getTime();
        long before90DaysTimestamp = currentTimestamp - 90 * millisecondsPerDay;
        return date.before(new Date(before90DaysTimestamp));
    }

    /**
     * @param date        时间
     * @param formateType 格式化的类型 形如 yyyy-MM-dd HH:mm:ss yyyy-MM-dd 等
     * @return
     */
    public static String DateToString(Date date, String formateType) {
        if (!StringUtils.hasText(formateType) || date == null) {
            return "";
        }
        SimpleDateFormat sdf = getFormater(formateType);
        return sdf.format(date);
    }

    /**
     * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
     *
     * @param strDate
     * @return
     */
    public static Date strToDateLong(String strDate) {
        SimpleDateFormat formatter = getFormater("yyyy-MM-dd HH:mm:ss");
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    /**
     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
     *
     * @param dateDate
     * @return
     */
    public static String dateToStrLong(Date dateDate) {
        SimpleDateFormat formatter = getFormater("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(dateDate);
        return dateString;
    }

    /**
     * 将短时间格式字符串转换为时间 yyyy-MM-dd
     *
     * @param strDate
     * @return
     */
    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = getFormater("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    /**
     * 将短时间格式时间转换为字符串 yyyy-MM-dd
     *
     * @param dateDate
     * @return
     */
    public static String dateToString(Date dateDate) {
        SimpleDateFormat formatter = getFormater("yyyy-MM-dd");
        String strtodate = formatter.format(dateDate);
        return strtodate;
    }

    public static String getCurrentDay() {
        SimpleDateFormat formatter = getFormater("yyyy-MM-dd");
        return formatter.format(new Date());
    }

    /**
     * 获取传入时间的月份的第一天
     *
     * @param date
     * @return
     */
    public static Date getMonthFirstDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取传入时间的月份的最后一天
     *
     * @param date
     * @return
     */
    public static Date getMonthLastDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当前日期
     */
    public static String getNowDate(String type) {
        if (!StringUtils.isEmpty(type)) {
            return new SimpleDateFormat(type).format(new Date());
        }
        return "";
    }

    /**
     * 获取当前时间
     */
    public static String getNowTime(String type) {
        if (!StringUtils.isEmpty(type)) {
            return new SimpleDateFormat(type).format(Calendar.getInstance().getTime());
        }
        return "";
    }

    /**
     * 统计用的日期,获取七天日期集合
     */
    public static List<String> getSevenDate() {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(new Date());
        calendar1.set(Calendar.HOUR_OF_DAY, 0);
        calendar1.set(Calendar.MINUTE, 0);
        calendar1.set(Calendar.SECOND, 0);
        Date zero = calendar1.getTime();
        List<String> dateList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < 8; i++) {
            Date date = DateUtils.addDays(zero, -i);
            String formatDate = sdf.format(date);
            dateList.add(formatDate);
        }
        return dateList;
    }

    public static Date templateDateStrToDate(String str) {
        if (!StringUtils.hasText(str)) {
            return null;
        }
        str = str.replace("T", "");
        str = str.replace("Z", "");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.sss");
        try {
            return simpleDateFormat.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    public static int getNowYear() {
        // 获取当前年
        return calendar.get(Calendar.YEAR);
    }

    public static String dataToStr(Date date, String format) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }


    public static String parseTemplateDate(String str) {
        return dataToStr(templateDateStrToDate(str), "yyyy年MM月dd日 HH时mm分ss秒");
    }

    public static Date formatStr(String str) {
        List<String> formatList = new ArrayList<>();
        formatList.add("yyyy-MM-dd");
        formatList.add("yyyy/MM/dd");
        for (String format : formatList) {
            Date date = tryToFormatStr(format, str);
            if (date != null) {
                return date;
            }
        }
        return null;
    }

    public static Date tryToFormatStr(String format, String str) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @param dateOfBirth 生日日期
     * @return 年龄
     * @apiNote 计算年龄
     */
    public static int getAge(Date dateOfBirth) {
        Calendar now = Calendar.getInstance();
        Calendar dob = Calendar.getInstance();

        dob.setTime(dateOfBirth);

        if (dob.after(now)) {
            throw new IllegalArgumentException("Can't be born in the future");
        }

        int age = now.get(Calendar.YEAR) - dob.get(Calendar.YEAR);

        if (now.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }

        return age;
    }

    /**
     * 获取过去七天
     */
    public static String getLastWeek() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, -7);
        return sdf.format(calendar.getTime());
    }


    /**
     * 获取一个月日期
     */
    public static String getOneMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -1);
        return sdf.format(calendar.getTime());
    }


    /**
     * 获取三个月日期
     */
    public static String getThreeMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -3);
        return sdf.format(calendar.getTime());
    }


    /**
     * 获取一年日期
     */
    public static String getOneYear() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.setTime(new Date());
        calendar.add(Calendar.YEAR, -1);
        return sdf.format(calendar.getTime());
    }


    public static String dateFormat(Date date, String format) {
        try {
            return new SimpleDateFormat(format).format(date);
        } catch (Exception e) {
            throw new RuntimeException("日期转换错误");
        }
    }


    public static Date addYears(Date date, int amount) {
        return add(date, 1, amount);
    }

    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    public static Date addWeeks(Date date, int amount) {
        return add(date, 3, amount);
    }

    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    public static Date addHours(Date date, int amount) {
        return add(date, 11, amount);
    }

    public static Date addMinutes(Date date, int amount) {
        return add(date, 12, amount);
    }

    public static Date addSeconds(Date date, int amount) {
        return add(date, 13, amount);
    }

    public static Date addMilliseconds(Date date, int amount) {
        return add(date, 14, amount);
    }

    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, amount);
            return c.getTime();
        }
    }

    public static Date combineDateTime(Date date, Time time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        Calendar timeCalendar = Calendar.getInstance();
        timeCalendar.setTimeInMillis(time.getTime());

        calendar.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
        calendar.set(Calendar.SECOND, timeCalendar.get(Calendar.SECOND));

        return calendar.getTime();
    }

    public static Date getYesterday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    public static Date getTomorrow(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    public static Date subtractMinutes(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, -minutes);
        return calendar.getTime();
    }

    /**
     * 计算两个日期之间相差的天数
     * @param date1 日期1（yyyy-MM-dd HH:mm:ss）
     * @param date2 日期2（yyyy-MM-dd HH:mm:ss）
     * @return Long 相差天数
     */
    public static Long timeGap(Date date1, Date date2) {
        long day = 24 * 60 * 60 * 1000;
        long time1 = date1.getTime();
        long time2 = date2.getTime();
        if (time1 > time2) {
            return (time1 - time2) / day;
        } else if (time1 < time2) {
            return (time2 - time1) / day;
        } else {
            return 0L;
        }
    }
}